#include "stdafx.h"
#include "BufferLoadImage.h"
#include "common_utils.h"

CBufferLoadImage::CBufferLoadImage(): 
m_pImage(NULL), 
m_hBuffer(NULL),
m_pScaleImage(NULL)
{

}

CBufferLoadImage::CBufferLoadImage(const void* pImgData, size_t uLen)
{
	Load(pImgData, uLen);
}

CBufferLoadImage::~CBufferLoadImage()
{
	Clear();
}

bool CBufferLoadImage::Load(const void* pImgData, size_t uLen)
{
	assert(pImgData);
	assert(uLen>0);
	Clear();

	if(!pImgData || uLen <= 0)
		return false;

	m_hBuffer  = ::GlobalAlloc(GMEM_MOVEABLE, uLen);
	if (!m_hBuffer)
		return false;

	BYTE* pBuffer = static_cast<BYTE*>(::GlobalLock(m_hBuffer));

	if(!pBuffer)
	{
		::GlobalFree(m_hBuffer);
		m_hBuffer = NULL;
		return false;
	}

	bool bRet = true;
	CopyMemory(pBuffer, pImgData, uLen);

	IStream* pStream = NULL;
	if (::CreateStreamOnHGlobal(m_hBuffer, FALSE, &pStream) == S_OK)
	{
		m_pImage = Gdiplus::Bitmap::FromStream(pStream);
		pStream->Release();
		if (!m_pImage || m_pImage->GetLastStatus() != Gdiplus::Ok)
		{
			delete m_pImage;
			m_pImage = NULL;
			bRet =false;
		}
	}
	else
	{
		::GlobalUnlock(m_hBuffer);
		Clear();
		bRet = false;
	}

	return bRet;
}

Gdiplus::Bitmap* CBufferLoadImage::GetImage() const { return m_pImage; }

bool CBufferLoadImage::GetScaleImgWrapper(CImageWrapper& imageWrapper, double dScaleFactor)
{
	if (FLOATCMP::nor_equal(dScaleFactor,1))
	{
		return GetImgWrapper(imageWrapper);
	}

	if(!m_pImage)
		return false;

	unsigned nImgWidth;
	unsigned nImgHeight;

	double dAspect = ((double)m_pImage->GetWidth())/m_pImage->GetHeight();
	if ( m_pImage->GetWidth() > m_pImage->GetHeight() )
	{
		nImgHeight = (unsigned)( m_pImage->GetHeight() / dScaleFactor + 0.5);
		nImgWidth = (unsigned)(nImgHeight*dAspect + 0.5);
	}
	else
	{
		nImgWidth = (unsigned)(m_pImage->GetWidth() / dScaleFactor + 0.5);
		nImgHeight = (unsigned)(nImgWidth/dAspect + 0.5);
	}


	//get bitmap
	if (m_pScaleImage)
	{
		delete m_pScaleImage;
	}
	m_pScaleImage = new Gdiplus::Bitmap(nImgWidth,nImgHeight,m_pImage->GetPixelFormat());

	Gdiplus::Graphics graph(m_pScaleImage);
	graph.SetInterpolationMode(Gdiplus::InterpolationModeBilinear);
	graph.DrawImage(m_pImage, Gdiplus::Rect(0,0, nImgWidth, nImgHeight), 0, 0, m_pImage->GetWidth(), m_pImage->GetHeight(), Gdiplus::UnitPixel);
	
//	CGdiImage img(m_pScaleImage);
//	img.Save("d:\\scale.bmp");

	//create image wrapper and itg image
	Gdiplus::BitmapData bmpData;
	Gdiplus::Rect imgRect(0, 0, m_pScaleImage->GetWidth(), m_pScaleImage->GetHeight());

	Gdiplus::Status status = m_pScaleImage->LockBits( &imgRect, Gdiplus::ImageLockModeRead, m_pScaleImage->GetPixelFormat(), &bmpData );

	bool bRet = false;
	if (SUCCEEDED(status))
	{
		int iPixelBytes = 1;
		switch(m_pImage->GetPixelFormat())
		{
		case PixelFormat24bppRGB:
			iPixelBytes=3;
			break;
		case PixelFormat8bppIndexed:
			iPixelBytes=1;
			break;
		}

		if(SUCCEEDED(imageWrapper.CreateImage(m_pScaleImage->GetWidth(), m_pScaleImage->GetHeight(), (const BYTE*)bmpData.Scan0, iPixelBytes, bmpData.Stride, 1, NULL)))
		{
			bRet = true;
		}
		m_pScaleImage->UnlockBits(&bmpData);
	}
	return true;
}

bool CBufferLoadImage::GetImgWrapper(CImageWrapper& imageWrapper)
{
	if(!m_pImage)
		return false;

	int iPixelBytes;
	Gdiplus::PixelFormat pixelFormat = m_pImage->GetPixelFormat();
	if (pixelFormat == PixelFormat24bppRGB)
	{
		iPixelBytes = 3;
	}
	else if (pixelFormat == PixelFormat8bppIndexed )
	{
		iPixelBytes = 1;
	}

	Gdiplus::BitmapData bmpData;
	int iWidth = m_pImage->GetWidth();
	int iHeight = m_pImage->GetHeight();
	Gdiplus::Rect imgRect(0, 0, iWidth, iHeight);

//	CGdiImage img(m_pImage);
//	img.Save("d:\\org.bmp");

	Gdiplus::Status status = m_pImage->LockBits( &imgRect, Gdiplus::ImageLockModeRead, pixelFormat, &bmpData );

	bool bRet = false;
	if (status == S_OK)
	{
		if(SUCCEEDED(imageWrapper.CreateImage(iWidth, iHeight, (const BYTE*)bmpData.Scan0, iPixelBytes, bmpData.Stride, 1, NULL)))
		{
			bRet = true;
		}
		m_pImage->UnlockBits(&bmpData);
	}

	return bRet;
}

void CBufferLoadImage::Clear()
{
	if(m_pImage){
		delete m_pImage;
		m_pImage = NULL;
	}
	if(m_hBuffer){
		::GlobalFree(m_hBuffer);
		m_hBuffer = NULL;
	}
	if (m_pScaleImage)
	{
		delete m_pScaleImage;
		m_pScaleImage = 0;
	}
}